package zpp_nape.dynamics;
import zpp_nape.Config;
import zpp_nape.Const;
import zpp_nape.util.Flags;
import DummyNapeMain;
import zpp_nape.util.Math;
import zpp_nape.util.Names;
import zpp_nape.util.Pool;
import zpp_nape.util.Lists;
import zpp_nape.shape.Circle;
import zpp_nape.shape.Edge;
import zpp_nape.space.Space;
import zpp_nape.shape.Polygon;
import zpp_nape.shape.Shape;
import zpp_nape.phys.FeatureMix;
import zpp_nape.phys.FluidProperties;
import zpp_nape.phys.Material;
import zpp_nape.phys.Body;
import zpp_nape.geom.AABB;
import zpp_nape.geom.Distance;
import zpp_nape.geom.Mat23;
import zpp_nape.geom.Vec2;
import zpp_nape.geom.VecMath;
import zpp_nape.geom.Collide;
import zpp_nape.dynamics.Contact;
import zpp_nape.dynamics.InteractionFilter;
import zpp_nape.constraint.Constraint;
import zpp_nape.dynamics.SpaceArbiterList;
import zpp_nape.constraint.Matrices;
import zpp_nape.constraint.PivotJoint;
import zpp_nape.constraint.WeldJoint;
import nape.util.Flags;
import nape.util.Lists;
import nape.util.Debug;
import nape.space.Space;
import nape.shape.Circle;
import nape.shape.Polygon;
import nape.shape.Edge;
import nape.shape.Shape;
import nape.phys.FluidProperties;
import nape.phys.Material;
import nape.phys.Body;
import nape.geom.AABB;
import nape.geom.Geom;
import nape.geom.Mat23;
import nape.geom.Vec2;
import nape.dynamics.Contact;
import nape.dynamics.Arbiter;
import nape.dynamics.InteractionFilter;
#if swc@:keep#end class ZPP_Arbiter{
    public var outer:Arbiter;
    public static var internal=false;
    #if(flash9&&flib)@:ns("flibdel")#end public inline function wrapper(){
        if(outer==null){
            internal=true;
            if(type==COL){
                colarb.outer_zn=new CollisionArbiter();
                outer=colarb.outer_zn;
            }
            else if(type==FLUID){
                fluidarb.outer_zn=new FluidArbiter();
                outer=fluidarb.outer_zn;
            }
            else outer=new Arbiter();
            internal=false;
            outer.zpp_inner=this;
        }
        return outer;
    }
    public function new(){}
    public var id:Int;
    public var stamp:Int;
    public var fstamp:Int;
    public var up_stamp:Int;
    public var sleep_stamp:Int;
    public var active:Bool;
    public var cleared:Bool;
    public var sleeping:Bool;
    public var invalidated:Bool;
    public var b1:ZPP_Body;
    public var b2:ZPP_Body;
    public var ws1:ZPP_Shape;
    public var ws2:ZPP_Shape;
    #if(flash9&&flib)@:ns("flibdel")#end public inline function swap_features(){
        {
            var t=b1;
            b1=b2;
            b2=t;
        };
        {
            var t=ws1;
            ws1=ws2;
            ws2=t;
        };
        if(colarb.kind==ZPP_ColArbiter.DD){
            var t=colarb.aDD.s1;
            colarb.aDD.s1=colarb.aDD.s2;
            colarb.aDD.s2=t;
        };
        else{
            var t=colarb.aSD.s1;
            colarb.aSD.s1=colarb.aSD.s2;
            colarb.aSD.s2=t;
        };
    }
    public var type:Int;
    public static inline var COL=0;
    public var colarb:ZPP_ColArbiter;
    public static inline var FLUID=1;
    public var fluidarb:ZPP_FluidArbiter;
    public static inline var SENSOR=2;
    public var sensorarb:ZPP_SensorArbiter;
    #if(flash9&&flib)@:ns("flibdel")#end public inline function lazyRetire(s:ZPP_Space,b:ZPP_Body){
        cleared=true;
        active=false;
        if(b==null){
            b1.arbiters.remove(this);
            b2.arbiters.remove(this);
        }
        else{
            if(b1==b)b2.arbiters.remove(this);
            else b1.arbiters.remove(this);
        }
        s.map_arb.remove(id);
        s.f_arbiters.modified=true;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function sup_assign(s1:ZPP_Shape,s2:ZPP_Shape,id:Int){
        b1=s1.body;
        ws1=s1;
        b2=s2.body;
        ws2=s2;
        this.id=id;
        b1.arbiters.add(this);
        b2.arbiters.add(this);
        cleared=false;
        active=true;
        sleeping=false;
    }
    public inline function sup_retire(){
        if(b1!=null){
            if(!cleared){
                b1.arbiters.remove(this);
                b2.arbiters.remove(this);
            }
            b1=b2=null;
        }
        active=false;
    }
}
#if swc@:keep#end class ZPP_SensorArbiter extends ZPP_Arbiter{
    static public var zpp_pool:ZPP_SensorArbiter;
    public var next:ZPP_SensorArbiter;
    #if(flash9&&flib)@:ns("flibdel")#end public inline function free(){}
    public function new(){
        super();
        type=ZPP_Arbiter.SENSOR;
        sensorarb=this;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function s_assign(s1:ZPP_Shape,s2:ZPP_Shape,id:Int){
        sup_assign(s1,s2,id);
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function retire(){
        sup_retire();
        {
            var o=this;
            {
                #if NAPE_ASSERT var res={
                    o!=null;
                };
                if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZPP_SensorArbiter"+", in obj: "+"this"+")");
                #end
            };
            o.free();
            o.next=ZPP_SensorArbiter.zpp_pool;
            ZPP_SensorArbiter.zpp_pool=o;
        };
    }
}
#if swc@:keep#end class ZPP_ColArbiter extends ZPP_Arbiter{
    public var outer_zn:CollisionArbiter;
    public var dyn_fric:Float;
    public var stat_fric:Float;
    public var restitution:Float;
    public var contacts:ZPP_Contact;
    public var wrap_contacts:ContactList;
    public var innards:ZPP_IContact;
    public var s1:ZPP_Shape;
    public var s2:ZPP_Shape;
    public function new(){
        super();
        contacts=new ZPP_Contact();
        innards=new ZPP_IContact();
        type=ZPP_Arbiter.COL;
        colarb=this;
    }
    public var kind:Int;
    public static inline var SD=0;
    public var aSD:ZSD;
    public static inline var DD=1;
    public var aDD:ZDD;
}
#if swc@:keep#end class ZPP_FluidArbiter extends ZPP_Arbiter{
    public var outer_zn:FluidArbiter;
    static public var zpp_pool:ZPP_FluidArbiter;
    public var next:ZPP_FluidArbiter;
    #if(flash9&&flib)@:ns("flibdel")#end public inline function free(){}
    public var centroidx:Float;
    public var centroidy:Float;
    public var overlap:Float;
    public var wMass:Float;
    public var wCoef:Float;
    public var targ_w:Float;
    public var r1x:Float;
    public var r1y:Float;
    public var r2x:Float;
    public var r2y:Float;
    public var nx:Float;
    public var ny:Float;
    public var vMass:Float;
    public var vCoef:Float;
    public var targ_v:Float;
    public var wrap_position:Vec2;
    public function getposition(){
        var me=this;
        wrap_position=new Vec2(centroidx,centroidy);
        wrap_position.zpp_inner.inuse=true;
        wrap_position.zpp_inner.immutable=true;
        wrap_position.zpp_inner._validate=function(){
            if(me.cleared)throw "Error: Arbiter not currently in use";
            {
                me.wrap_position.zpp_inner.x=me.centroidx;
                me.wrap_position.zpp_inner.y=me.centroidy;
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](me.wrap_position.zpp_inner.x);
                            ret;
                            #else Math.isNaN(me.wrap_position.zpp_inner.x);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(me.wrap_position.zpp_inner.x)"+") :: "+("vec_set(in n: "+"me.wrap_position.zpp_inner."+",in x: "+"me.centroidx"+",in y: "+"me.centroidy"+")");
                    #end
                };
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](me.wrap_position.zpp_inner.y);
                            ret;
                            #else Math.isNaN(me.wrap_position.zpp_inner.y);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(me.wrap_position.zpp_inner.y)"+") :: "+("vec_set(in n: "+"me.wrap_position.zpp_inner."+",in x: "+"me.centroidx"+",in y: "+"me.centroidy"+")");
                    #end
                };
            };
        }
    }
    public function new(){
        super();
        type=ZPP_Arbiter.FLUID;
        fluidarb=this;
    }
    public inline function f_assign(s1:ZPP_Shape,s2:ZPP_Shape,id:Int){
        sup_assign(s1,s2,id);
        {
            nx=0;
            ny=1;
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](nx);
                        ret;
                        #else Math.isNaN(nx);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(nx)"+") :: "+("vec_set(in n: "+"n"+",in x: "+"0"+",in y: "+"1"+")");
                #end
            };
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](ny);
                        ret;
                        #else Math.isNaN(ny);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(ny)"+") :: "+("vec_set(in n: "+"n"+",in x: "+"0"+",in y: "+"1"+")");
                #end
            };
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function inject(area:Float,cx:Float,cy:Float){
        overlap=area;
        {
            centroidx=cx;
            centroidy=cy;
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](centroidx);
                        ret;
                        #else Math.isNaN(centroidx);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(centroidx)"+") :: "+("vec_set(in n: "+"centroid"+",in x: "+"cx"+",in y: "+"cy"+")");
                #end
            };
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](centroidy);
                        ret;
                        #else Math.isNaN(centroidy);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(centroidy)"+") :: "+("vec_set(in n: "+"centroid"+",in x: "+"cx"+",in y: "+"cy"+")");
                #end
            };
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function retire(){
        sup_retire();
        {
            var o=this;
            {
                #if NAPE_ASSERT var res={
                    o!=null;
                };
                if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZPP_FluidArbiter"+", in obj: "+"this"+")");
                #end
            };
            o.free();
            o.next=ZPP_FluidArbiter.zpp_pool;
            ZPP_FluidArbiter.zpp_pool=o;
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function applyImpulse(){
        var vrx:Float=(b2.velx-r2y*b2.angvel)-(b1.velx-r1y*b1.angvel);
        var vry:Float=(b2.vely+r2x*b2.angvel)-(b1.vely+r1x*b1.angvel);
        {
            #if NAPE_ASSERT var res={
                !({
                    #if flash9 var ret:Bool=untyped __global__["isNaN"](vrx);
                    ret;
                    #else Math.isNaN(vrx);
                    #end
                });
            };
            if(!res)throw "assert("+"!assert_isNaN(vrx)"+") :: "+("vec_new(in n: "+"vr"+",in x: "+"(b2.velx-r2y*b2.angvel)-(b1.velx-r1y*b1.angvel)"+",in y: "+"(b2.vely+r2x*b2.angvel)-(b1.vely+r1x*b1.angvel)"+")");
            #end
        };
        {
            #if NAPE_ASSERT var res={
                !({
                    #if flash9 var ret:Bool=untyped __global__["isNaN"](vry);
                    ret;
                    #else Math.isNaN(vry);
                    #end
                });
            };
            if(!res)throw "assert("+"!assert_isNaN(vry)"+") :: "+("vec_new(in n: "+"vr"+",in x: "+"(b2.velx-r2y*b2.angvel)-(b1.velx-r1y*b1.angvel)"+",in y: "+"(b2.vely+r2x*b2.angvel)-(b1.vely+r1x*b1.angvel)"+")");
            #end
        };
        var vrn=(vrx*nx+vry*ny)-targ_v;
        var v_damp=-vrn*vCoef;
        targ_v=vrn+v_damp;
        var jx:Float=nx*v_damp*vMass;
        var jy:Float=ny*v_damp*vMass;
        {
            #if NAPE_ASSERT var res={
                !({
                    #if flash9 var ret:Bool=untyped __global__["isNaN"](jx);
                    ret;
                    #else Math.isNaN(jx);
                    #end
                });
            };
            if(!res)throw "assert("+"!assert_isNaN(jx)"+") :: "+("vec_new(in n: "+"j"+",in x: "+"nx*v_damp*vMass"+",in y: "+"ny*v_damp*vMass"+")");
            #end
        };
        {
            #if NAPE_ASSERT var res={
                !({
                    #if flash9 var ret:Bool=untyped __global__["isNaN"](jy);
                    ret;
                    #else Math.isNaN(jy);
                    #end
                });
            };
            if(!res)throw "assert("+"!assert_isNaN(jy)"+") :: "+("vec_new(in n: "+"j"+",in x: "+"nx*v_damp*vMass"+",in y: "+"ny*v_damp*vMass"+")");
            #end
        };
        {
            var t=(b1.imass);
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                        ret;
                        #else Math.isNaN(t);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_subeq(in a: "+"b1.vel"+",in b: "+"j"+",in s: "+"b1.imass"+")");
                #end
            };
            b1.velx-=jx*t;
            b1.vely-=jy*t;
        };
        {
            var t=(b2.imass);
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                        ret;
                        #else Math.isNaN(t);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"b2.vel"+",in b: "+"j"+",in s: "+"b2.imass"+")");
                #end
            };
            b2.velx+=jx*t;
            b2.vely+=jy*t;
        };
        b1.angvel-=b1.iinertia*(jy*r1x-jx*r1y);
        b2.angvel+=b2.iinertia*(jy*r2x-jx*r2y);
        var wrn=b1.angvel-b2.angvel;
        var w_damp=wrn*wCoef;
        targ_w=wrn-w_damp;
        var j_damp=w_damp*wMass;
        b1.angvel-=j_damp*b1.iinertia;
        b2.angvel+=j_damp*b2.iinertia;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function preStep(s:ZPP_Space,dt:Float){
        var tViscosity=0.0;
        if(ws1.fluidEnabled){
            ws2.validate_angDrag();
            tViscosity+=ws1.fluidProperties.viscosity*ws2.angDrag*overlap/ws2.area;
        }
        if(ws2.fluidEnabled){
            ws1.validate_angDrag();
            tViscosity+=ws2.fluidProperties.viscosity*ws1.angDrag*overlap/ws1.area;
        }
        var iSum=b1.sinertia+b2.sinertia;
        wMass=1/iSum;
        wCoef=1-Math.exp(-tViscosity*tViscosity*dt*ZPP_Config.FLUID_COEF_ANG);
        targ_w=0.0;
        {
            r1x=centroidx-b1.posx;
            r1y=centroidy-b1.posy;
        };
        {
            r2x=centroidx-b2.posx;
            r2y=centroidy-b2.posy;
        };
        var vrnx:Float=(b2.velx-r2y*b2.angvel)-(b1.velx-r1y*b1.angvel);
        var vrny:Float=(b2.vely+r2x*b2.angvel)-(b1.vely+r1x*b1.angvel);
        {
            #if NAPE_ASSERT var res={
                !({
                    #if flash9 var ret:Bool=untyped __global__["isNaN"](vrnx);
                    ret;
                    #else Math.isNaN(vrnx);
                    #end
                });
            };
            if(!res)throw "assert("+"!assert_isNaN(vrnx)"+") :: "+("vec_new(in n: "+"vrn"+",in x: "+"(b2.velx-r2y*b2.angvel)-(b1.velx-r1y*b1.angvel)"+",in y: "+"(b2.vely+r2x*b2.angvel)-(b1.vely+r1x*b1.angvel)"+")");
            #end
        };
        {
            #if NAPE_ASSERT var res={
                !({
                    #if flash9 var ret:Bool=untyped __global__["isNaN"](vrny);
                    ret;
                    #else Math.isNaN(vrny);
                    #end
                });
            };
            if(!res)throw "assert("+"!assert_isNaN(vrny)"+") :: "+("vec_new(in n: "+"vrn"+",in x: "+"(b2.velx-r2y*b2.angvel)-(b1.velx-r1y*b1.angvel)"+",in y: "+"(b2.vely+r2x*b2.angvel)-(b1.vely+r1x*b1.angvel)"+")");
            #end
        };
        if((vrnx*vrnx+vrny*vrny)<ZPP_Const.EPSILON){}
        else{
            {
                var d=(vrnx*vrnx+vrny*vrny);
                {
                    #if NAPE_ASSERT var res={
                        d!=0.0;
                    };
                    if(!res)throw "assert("+"d!=0.0"+") :: "+("vec_normalise(in n: "+"vrn"+")");
                    #end
                };
                var imag=ZPP_Math.invsqrt(d);
                {
                    var t=(imag);
                    {
                        #if NAPE_ASSERT var res={
                            !({
                                #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                ret;
                                #else Math.isNaN(t);
                                #end
                            });
                        };
                        if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_muleq(in a: "+"vrn"+",in s: "+"imag"+")");
                        #end
                    };
                    vrnx*=t;
                    vrny*=t;
                };
            };
            {
                nx=vrnx;
                ny=vrny;
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](nx);
                            ret;
                            #else Math.isNaN(nx);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(nx)"+") :: "+("vec_set(in n: "+"n"+",in x: "+"vrnx"+",in y: "+"vrny"+")");
                    #end
                };
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](ny);
                            ret;
                            #else Math.isNaN(ny);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(ny)"+") :: "+("vec_set(in n: "+"n"+",in x: "+"vrnx"+",in y: "+"vrny"+")");
                    #end
                };
            };
        }
        var tViscosity=0.0;
        if(ws1.fluidEnabled){
            var f=-ws1.fluidProperties.viscosity*overlap/ws2.area;
            if(ws2.type==ZPP_Flags.id_ShapeType_CIRCLE)tViscosity-=f*ws2.circle.radius*ZPP_Config.FLUID_COEF_LIN/(2*ws2.circle.radius*Math.PI);
            else{
                var poly=ws2.polygon;
                var bord=0.0;
                var acc=0.0;
                {
                    var cx_ite=poly.edges.begin();
                    while(cx_ite!=null){
                        var ex=cx_ite.elem();
                        {
                            bord+=ex.length;
                            var fact=f*ex.length*(ex.gnormx*nx+ex.gnormy*ny);
                            if(fact>0)fact=fact*=-ZPP_Config.ANGDRAGCOEF_VACUUM;
                            acc-=fact*0.5*ZPP_Config.FLUID_COEF_LIN;
                        };
                        cx_ite=cx_ite.next;
                    }
                };
                tViscosity+=acc/bord;
            }
        }
        if(ws2.fluidEnabled){
            var f=-ws2.fluidProperties.viscosity*overlap/ws1.area;
            if(ws1.type==ZPP_Flags.id_ShapeType_CIRCLE)tViscosity-=f*ws1.circle.radius*ZPP_Config.FLUID_COEF_LIN/(2*ws1.circle.radius*Math.PI);
            else{
                var poly=ws1.polygon;
                var bord=0.0;
                var acc=0.0;
                {
                    var cx_ite=poly.edges.begin();
                    while(cx_ite!=null){
                        var ex=cx_ite.elem();
                        {
                            bord+=ex.length;
                            var fact=f*ex.length*(ex.gnormx*nx+ex.gnormy*ny);
                            if(fact>0)fact=fact*=-ZPP_Config.ANGDRAGCOEF_VACUUM;
                            acc-=fact*0.5*ZPP_Config.FLUID_COEF_LIN;
                        };
                        cx_ite=cx_ite.next;
                    }
                };
                tViscosity+=acc/bord;
            }
        }
        var k=b1.smass+b1.sinertia*ZPP_Math.sqr((ny*r1x-nx*r1y))+b2.smass+b2.sinertia*ZPP_Math.sqr((ny*r2x-nx*r2y));
        vMass=1/k;
        targ_v=0;
        vCoef=1-Math.exp(-tViscosity*dt*k);
        var buoyx:Float=0;
        var buoyy:Float=0;
        {
            #if NAPE_ASSERT var res={
                !({
                    #if flash9 var ret:Bool=untyped __global__["isNaN"](buoyx);
                    ret;
                    #else Math.isNaN(buoyx);
                    #end
                });
            };
            if(!res)throw "assert("+"!assert_isNaN(buoyx)"+") :: "+("vec_new(in n: "+"buoy"+",in x: "+"0"+",in y: "+"0"+")");
            #end
        };
        {
            #if NAPE_ASSERT var res={
                !({
                    #if flash9 var ret:Bool=untyped __global__["isNaN"](buoyy);
                    ret;
                    #else Math.isNaN(buoyy);
                    #end
                });
            };
            if(!res)throw "assert("+"!assert_isNaN(buoyy)"+") :: "+("vec_new(in n: "+"buoy"+",in x: "+"0"+",in y: "+"0"+")");
            #end
        };
        if(ws1.fluidEnabled&&ws2.fluidEnabled){
            var mass1=overlap*ws1.fluidProperties.density;
            var mass2=overlap*ws2.fluidProperties.density;
            if(mass1>mass2){
                var t=(mass1+mass2);
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                            ret;
                            #else Math.isNaN(t);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_subeq(in a: "+"buoy"+",in b: "+"s.gravity"+",in s: "+"mass1+mass2"+")");
                    #end
                };
                buoyx-=s.gravityx*t;
                buoyy-=s.gravityy*t;
            };
            else if(mass1<mass2){
                var t=(mass1+mass2);
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                            ret;
                            #else Math.isNaN(t);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"buoy"+",in b: "+"s.gravity"+",in s: "+"mass1+mass2"+")");
                    #end
                };
                buoyx+=s.gravityx*t;
                buoyy+=s.gravityy*t;
            };
            else if((ws1.worldCOMx*s.gravityx+ws1.worldCOMy*s.gravityy)>(ws2.worldCOMx*s.gravityx+ws2.worldCOMy*s.gravityy)){
                var t=(mass1+mass2);
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                            ret;
                            #else Math.isNaN(t);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_subeq(in a: "+"buoy"+",in b: "+"s.gravity"+",in s: "+"mass1+mass2"+")");
                    #end
                };
                buoyx-=s.gravityx*t;
                buoyy-=s.gravityy*t;
            };
            else{
                var t=(mass1+mass2);
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                            ret;
                            #else Math.isNaN(t);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"buoy"+",in b: "+"s.gravity"+",in s: "+"mass1+mass2"+")");
                    #end
                };
                buoyx+=s.gravityx*t;
                buoyy+=s.gravityy*t;
            };
        }
        else if(ws1.fluidEnabled){
            var mass=overlap*ws1.fluidProperties.density;
            {
                var t=(mass);
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                            ret;
                            #else Math.isNaN(t);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_subeq(in a: "+"buoy"+",in b: "+"s.gravity"+",in s: "+"mass"+")");
                    #end
                };
                buoyx-=s.gravityx*t;
                buoyy-=s.gravityy*t;
            };
        }
        else if(ws2.fluidEnabled){
            var mass=overlap*ws2.fluidProperties.density;
            {
                var t=(mass);
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                            ret;
                            #else Math.isNaN(t);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"buoy"+",in b: "+"s.gravity"+",in s: "+"mass"+")");
                    #end
                };
                buoyx+=s.gravityx*t;
                buoyy+=s.gravityy*t;
            };
        }
        if(b1.isDynamic()){
            {
                var t=(1.0);
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                            ret;
                            #else Math.isNaN(t);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_subeq(in a: "+"b1.force"+",in b: "+"buoy"+",in s: "+"1.0"+")");
                    #end
                };
                b1.forcex-=buoyx*t;
                b1.forcey-=buoyy*t;
            };
            b1.torque-=(buoyy*r1x-buoyx*r1y);
        }
        if(b2.isDynamic()){
            {
                var t=(1.0);
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                            ret;
                            #else Math.isNaN(t);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"b2.force"+",in b: "+"buoy"+",in s: "+"1.0"+")");
                    #end
                };
                b2.forcex+=buoyx*t;
                b2.forcey+=buoyy*t;
            };
            b2.torque+=(buoyy*r2x-buoyx*r2y);
        }
    }
}
typedef ArbSD=ZSD;
typedef ArbDD=ZDD;

@:keep#if swc@:keep#end class ZDD extends ZPP_ColArbiter{
    static public var zpp_pool:ZDD;
    public var next:ZDD;
    public function new(){
        super();
        kind=ZPP_ColArbiter.DD;
        aDD=this;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function free(){}
    #if(flash9&&flib)@:ns("flibdel")#end public inline function retire(){
        sup_retire();
        while(!contacts.empty()){
            {
                var o=contacts.pop_unsafe();
                {
                    #if NAPE_ASSERT var res={
                        o!=null;
                    };
                    if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZPP_Contact"+", in obj: "+"contacts.pop_unsafe()"+")");
                    #end
                };
                o.free();
                o.next=ZPP_Contact.zpp_pool;
                ZPP_Contact.zpp_pool=o;
            };
            innards.pop();
        }
        {
            var o=this;
            {
                #if NAPE_ASSERT var res={
                    o!=null;
                };
                if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZDD"+", in obj: "+"this"+")");
                #end
            };
            o.free();
            o.next=ZDD.zpp_pool;
            ZDD.zpp_pool=o;
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function injectContact(px:Float,py:Float,nx:Float,ny:Float,dist:Float,hash:Int){
        var c:ZPP_Contact=null;
        {
            var cx_ite=contacts.begin();
            while(cx_ite!=null){
                var cur=cx_ite.elem();
                if(hash==cur.hash){
                    c=cur;
                    break;
                };
                cx_ite=cx_ite.next;
            }
        };
        if(c==null){
            c={
                if(ZPP_Contact.zpp_pool==null)new ZPP_Contact();
                else{
                    var ret=ZPP_Contact.zpp_pool;
                    ZPP_Contact.zpp_pool=ret.next;
                    ret;
                }
            };
            var ci=c.inner;
            ci.jnAcc=ci.jtAcc=0;
            c.sBias=-1;
            c.hash=hash;
            c.fresh=true;
            c.arbiter=this;
            contacts.add(c);
            innards.add(ci);
        }
        else c.fresh=c.stamp+1!=stamp;
        var ci=c.inner;
        {
            ci.px=px;
            ci.py=py;
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](ci.px);
                        ret;
                        #else Math.isNaN(ci.px);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(ci.px)"+") :: "+("vec_set(in n: "+"ci.p"+",in x: "+"px"+",in y: "+"py"+")");
                #end
            };
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](ci.py);
                        ret;
                        #else Math.isNaN(ci.py);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(ci.py)"+") :: "+("vec_set(in n: "+"ci.p"+",in x: "+"px"+",in y: "+"py"+")");
                #end
            };
        };
        {
            ci.nx=nx;
            ci.ny=ny;
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](ci.nx);
                        ret;
                        #else Math.isNaN(ci.nx);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(ci.nx)"+") :: "+("vec_set(in n: "+"ci.n"+",in x: "+"nx"+",in y: "+"ny"+")");
                #end
            };
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](ci.ny);
                        ret;
                        #else Math.isNaN(ci.ny);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(ci.ny)"+") :: "+("vec_set(in n: "+"ci.n"+",in x: "+"nx"+",in y: "+"ny"+")");
                #end
            };
        };
        c.dist=dist;
        c.stamp=stamp;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function assign(s1:ZPP_Shape,s2:ZPP_Shape,id:Int){
        sup_assign(s1,s2,id);
        this.s1=s1;
        this.s2=s2;
        calcProperties();
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function calcProperties(){
        restitution=if(s1.material.elasticity==ZPP_Const.POSINF||s2.material.elasticity==ZPP_Const.POSINF)1 else ZPP_Math.sqrt(s1.material.elasticity*s2.material.elasticity);
        if(restitution>1)restitution=1;
        dyn_fric=ZPP_Math.sqrt(s1.material.dynamicFriction*s2.material.dynamicFriction);
        stat_fric=ZPP_Math.sqrt(s1.material.staticFriction*s2.material.staticFriction);
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function preStep(){
        if(invalidated){
            invalidated=false;
            calcProperties();
        }
        var mass_sum=(if(!false)b1.smass else 0)+b2.smass;
        var pre=null;
        var prei=null;
        var cx_itei=innards.begin();
        {
            var cx_ite=contacts.begin();
            while(cx_ite!=null){
                var c=cx_ite.elem();
                {
                    if(c.stamp+ZPP_Config.PERSIST<stamp){
                        cx_ite=contacts.erase(pre);
                        cx_itei=innards.erase(prei);
                        {
                            var o=c;
                            {
                                #if NAPE_ASSERT var res={
                                    o!=null;
                                };
                                if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZPP_Contact"+", in obj: "+"c"+")");
                                #end
                            };
                            o.free();
                            o.next=ZPP_Contact.zpp_pool;
                            ZPP_Contact.zpp_pool=o;
                        };
                        continue;
                    }
                    var ci=c.inner;
                    var pact=ci.active;
                    ci.active=c.stamp==stamp;
                    if(pact!=ci.active)contacts.modified=true;
                    if(ci.active){
                        var kn=mass_sum;
                        var kt=mass_sum;
                        if(!false){
                            {
                                ci.r1x=ci.px-b1.posx;
                                ci.r1y=ci.py-b1.posy;
                            };
                            var rcn=(ci.ny*ci.r1x-ci.nx*ci.r1y);
                            var rct=(ci.r1x*ci.nx+ci.r1y*ci.ny);
                            kn+=b1.sinertia*rcn*rcn;
                            kt+=b1.sinertia*rct*rct;
                        };
                        {
                            {
                                ci.r2x=ci.px-b2.posx;
                                ci.r2y=ci.py-b2.posy;
                            };
                            var rcn=(ci.ny*ci.r2x-ci.nx*ci.r2y);
                            var rct=(ci.r2x*ci.nx+ci.r2y*ci.ny);
                            kn+=b2.sinertia*rcn*rcn;
                            kt+=b2.sinertia*rct*rct;
                        };
                        ci.nMass=if(kn<ZPP_Const.EPSILON)0 else 1.0/kn;
                        ci.tMass=if(kt<ZPP_Const.EPSILON)0 else 1.0/kt;
                        var vrx:Float;
                        var vry:Float;
                        {
                            vrx=(if(!false)ci.r1y*b1.angvel else 0)-(ci.r2y*b2.angvel)-(if(!false)b1.velx else 0)+(b2.velx);
                            vry=(ci.r2x*b2.angvel)-(if(!false)ci.r1x*b1.angvel else 0)-(if(!false)b1.vely else 0)+(b2.vely);
                        };
                        var vdot=(ci.nx*vrx+ci.ny*vry);
                        ci.bias=c.dist+ZPP_Config.OVERLAP;
                        var nb=ZPP_Config.MIN_BIAS_COEF;
                        var delta=1-ZPP_Config.VEL_BIAS_COEF*vdot*vdot;
                        if(delta<0)delta=0;
                        delta-=c.dist*ZPP_Config.BIAS_PEN_COEF;
                        if(delta<0)delta=0;
                        if(delta>1)delta=1;
                        nb+=ZPP_Config.DEL_BIAS_COEF*delta;
                        if(nb>1)nb=1;
                        ci.jbAcc=0;
                        if(c.sBias==-1)c.sBias=nb;
                        else c.sBias=ZPP_Config.INT_BIAS_COEF*c.sBias+ZPP_Config.SUB_BIAS_COEF*nb;
                        if(ci.bias>0)ci.bias=0;
                        else ci.bias=-c.sBias*ci.bias;
                        ci.bounce=vdot*restitution;
                        vdot=(vry*ci.nx-vrx*ci.ny);
                        if(vdot*vdot>ZPP_Config.STATIC_VELSQ){
                            ci.friction=dyn_fric;
                        }
                        else{
                            ci.friction=stat_fric;
                        }
                    }
                    pre=cx_ite;
                    prei=cx_itei;
                    cx_itei=cx_itei.next;
                };
                cx_ite=cx_ite.next;
            }
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function applyImpulseCache(){
        {
            var cx_ite=contacts.begin();
            while(cx_ite!=null){
                var c=cx_ite.elem();
                {
                    var ci=c.inner;
                    if(!ci.active){
                        cx_ite=cx_ite.next;
                        continue;
                    };
                    c.pjnAcc=ci.jnAcc;
                    c.pjtAcc=ci.jtAcc;
                    {
                        var jx=ci.nx*ci.jnAcc-ci.ny*ci.jtAcc;
                        var jy=ci.ny*ci.jnAcc+ci.nx*ci.jtAcc;
                        if(!false){
                            {
                                var t=(b1.imass);
                                {
                                    #if NAPE_ASSERT var res={
                                        !({
                                            #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                            ret;
                                            #else Math.isNaN(t);
                                            #end
                                        });
                                    };
                                    if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_subeq(in a: "+"b1.vel"+",in b: "+"j"+",in s: "+"b1.imass"+")");
                                    #end
                                };
                                b1.velx-=jx*t;
                                b1.vely-=jy*t;
                            };
                            b1.angvel-=b1.iinertia*(jy*ci.r1x-jx*ci.r1y);
                        }
                        {
                            var t=(b2.imass);
                            {
                                #if NAPE_ASSERT var res={
                                    !({
                                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                        ret;
                                        #else Math.isNaN(t);
                                        #end
                                    });
                                };
                                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"b2.vel"+",in b: "+"j"+",in s: "+"b2.imass"+")");
                                #end
                            };
                            b2.velx+=jx*t;
                            b2.vely+=jy*t;
                        };
                        b2.angvel+=b2.iinertia*(jy*ci.r2x-jx*ci.r2y);
                    };
                };
                cx_ite=cx_ite.next;
            }
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function applyImpulse(elastic:Bool){
        {
            var cx_ite=innards.begin();
            while(cx_ite!=null){
                var c=cx_ite.elem();
                {
                    if(!c.active){
                        cx_ite=cx_ite.next;
                        continue;
                    };
                    var vrx:Float;
                    var vry:Float;
                    {
                        vrx=(if(!false)c.r1y*b1.bias_angvel else 0)-(c.r2y*b2.bias_angvel)-(if(!false)b1.bias_velx else 0)+(b2.bias_velx);
                        vry=(c.r2x*b2.bias_angvel)-(if(!false)c.r1x*b1.bias_angvel else 0)-(if(!false)b1.bias_vely else 0)+(b2.bias_vely);
                    };
                    var jbn=(c.bias-(vrx*c.nx+vry*c.ny))*c.nMass;
                    var jbOld=c.jbAcc;
                    var cjbAcc=jbOld+jbn;
                    if(cjbAcc<0)cjbAcc=0;
                    jbn=cjbAcc-jbOld;
                    c.jbAcc=cjbAcc;
                    {
                        var jx=c.nx*jbn-c.ny*0;
                        var jy=c.ny*jbn+c.nx*0;
                        if(!false){
                            {
                                var t=(b1.imass);
                                {
                                    #if NAPE_ASSERT var res={
                                        !({
                                            #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                            ret;
                                            #else Math.isNaN(t);
                                            #end
                                        });
                                    };
                                    if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_subeq(in a: "+"b1.bias_vel"+",in b: "+"j"+",in s: "+"b1.imass"+")");
                                    #end
                                };
                                b1.bias_velx-=jx*t;
                                b1.bias_vely-=jy*t;
                            };
                            b1.bias_angvel-=b1.iinertia*(jy*c.r1x-jx*c.r1y);
                        }
                        {
                            var t=(b2.imass);
                            {
                                #if NAPE_ASSERT var res={
                                    !({
                                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                        ret;
                                        #else Math.isNaN(t);
                                        #end
                                    });
                                };
                                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"b2.bias_vel"+",in b: "+"j"+",in s: "+"b2.imass"+")");
                                #end
                            };
                            b2.bias_velx+=jx*t;
                            b2.bias_vely+=jy*t;
                        };
                        b2.bias_angvel+=b2.iinertia*(jy*c.r2x-jx*c.r2y);
                    };
                    {
                        vrx=(if(!false)c.r1y*b1.angvel else 0)-(c.r2y*b2.angvel)-(if(!false)b1.velx else 0)+(b2.velx);
                        vry=(c.r2x*b2.angvel)-(if(!false)c.r1x*b1.angvel else 0)-(if(!false)b1.vely else 0)+(b2.vely);
                    };
                    var jn=((if(elastic)c.bounce else 0)+(c.nx*vrx+c.ny*vry))*c.nMass;
                    var jnOld=c.jnAcc;
                    var cjnAcc=jnOld-jn;
                    if(cjnAcc<0)cjnAcc=0;
                    jn=cjnAcc-jnOld;
                    c.jnAcc=cjnAcc;
                    var jt=((vry*c.nx-vrx*c.ny))*c.tMass;
                    var jtMax=c.friction*c.jnAcc;
                    var jtOld=c.jtAcc;
                    var cjtAcc=jtOld-jt;
                    if(cjtAcc>jtMax)cjtAcc=jtMax else if(cjtAcc<-jtMax)cjtAcc=-jtMax;
                    jt=cjtAcc-jtOld;
                    c.jtAcc=cjtAcc;
                    {
                        var jx=c.nx*jn-c.ny*jt;
                        var jy=c.ny*jn+c.nx*jt;
                        if(!false){
                            {
                                var t=(b1.imass);
                                {
                                    #if NAPE_ASSERT var res={
                                        !({
                                            #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                            ret;
                                            #else Math.isNaN(t);
                                            #end
                                        });
                                    };
                                    if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_subeq(in a: "+"b1.vel"+",in b: "+"j"+",in s: "+"b1.imass"+")");
                                    #end
                                };
                                b1.velx-=jx*t;
                                b1.vely-=jy*t;
                            };
                            b1.angvel-=b1.iinertia*(jy*c.r1x-jx*c.r1y);
                        }
                        {
                            var t=(b2.imass);
                            {
                                #if NAPE_ASSERT var res={
                                    !({
                                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                        ret;
                                        #else Math.isNaN(t);
                                        #end
                                    });
                                };
                                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"b2.vel"+",in b: "+"j"+",in s: "+"b2.imass"+")");
                                #end
                            };
                            b2.velx+=jx*t;
                            b2.vely+=jy*t;
                        };
                        b2.angvel+=b2.iinertia*(jy*c.r2x-jx*c.r2y);
                    };
                };
                cx_ite=cx_ite.next;
            }
        };
    }
}
@:keep#if swc@:keep#end class ZSD extends ZPP_ColArbiter{
    static public var zpp_pool:ZSD;
    public var next:ZSD;
    public function new(){
        super();
        kind=ZPP_ColArbiter.SD;
        aSD=this;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function free(){}
    #if(flash9&&flib)@:ns("flibdel")#end public inline function retire(){
        sup_retire();
        while(!contacts.empty()){
            {
                var o=contacts.pop_unsafe();
                {
                    #if NAPE_ASSERT var res={
                        o!=null;
                    };
                    if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZPP_Contact"+", in obj: "+"contacts.pop_unsafe()"+")");
                    #end
                };
                o.free();
                o.next=ZPP_Contact.zpp_pool;
                ZPP_Contact.zpp_pool=o;
            };
            innards.pop();
        }
        {
            var o=this;
            {
                #if NAPE_ASSERT var res={
                    o!=null;
                };
                if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZSD"+", in obj: "+"this"+")");
                #end
            };
            o.free();
            o.next=ZSD.zpp_pool;
            ZSD.zpp_pool=o;
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function injectContact(px:Float,py:Float,nx:Float,ny:Float,dist:Float,hash:Int){
        var c:ZPP_Contact=null;
        {
            var cx_ite=contacts.begin();
            while(cx_ite!=null){
                var cur=cx_ite.elem();
                if(hash==cur.hash){
                    c=cur;
                    break;
                };
                cx_ite=cx_ite.next;
            }
        };
        if(c==null){
            c={
                if(ZPP_Contact.zpp_pool==null)new ZPP_Contact();
                else{
                    var ret=ZPP_Contact.zpp_pool;
                    ZPP_Contact.zpp_pool=ret.next;
                    ret;
                }
            };
            var ci=c.inner;
            ci.jnAcc=ci.jtAcc=0;
            c.sBias=-1;
            c.hash=hash;
            c.fresh=true;
            c.arbiter=this;
            contacts.add(c);
            innards.add(ci);
        }
        else c.fresh=c.stamp+1!=stamp;
        var ci=c.inner;
        {
            ci.px=px;
            ci.py=py;
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](ci.px);
                        ret;
                        #else Math.isNaN(ci.px);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(ci.px)"+") :: "+("vec_set(in n: "+"ci.p"+",in x: "+"px"+",in y: "+"py"+")");
                #end
            };
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](ci.py);
                        ret;
                        #else Math.isNaN(ci.py);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(ci.py)"+") :: "+("vec_set(in n: "+"ci.p"+",in x: "+"px"+",in y: "+"py"+")");
                #end
            };
        };
        {
            ci.nx=nx;
            ci.ny=ny;
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](ci.nx);
                        ret;
                        #else Math.isNaN(ci.nx);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(ci.nx)"+") :: "+("vec_set(in n: "+"ci.n"+",in x: "+"nx"+",in y: "+"ny"+")");
                #end
            };
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](ci.ny);
                        ret;
                        #else Math.isNaN(ci.ny);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(ci.ny)"+") :: "+("vec_set(in n: "+"ci.n"+",in x: "+"nx"+",in y: "+"ny"+")");
                #end
            };
        };
        c.dist=dist;
        c.stamp=stamp;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function assign(s1:ZPP_Shape,s2:ZPP_Shape,id:Int){
        sup_assign(s1,s2,id);
        this.s1=s1;
        this.s2=s2;
        calcProperties();
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function calcProperties(){
        restitution=if(s1.material.elasticity==ZPP_Const.POSINF||s2.material.elasticity==ZPP_Const.POSINF)1 else ZPP_Math.sqrt(s1.material.elasticity*s2.material.elasticity);
        if(restitution>1)restitution=1;
        dyn_fric=ZPP_Math.sqrt(s1.material.dynamicFriction*s2.material.dynamicFriction);
        stat_fric=ZPP_Math.sqrt(s1.material.staticFriction*s2.material.staticFriction);
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function preStep(){
        if(invalidated){
            invalidated=false;
            calcProperties();
        }
        var mass_sum=(if(!true)b1.smass else 0)+b2.smass;
        var pre=null;
        var prei=null;
        var cx_itei=innards.begin();
        {
            var cx_ite=contacts.begin();
            while(cx_ite!=null){
                var c=cx_ite.elem();
                {
                    if(c.stamp+ZPP_Config.PERSIST<stamp){
                        cx_ite=contacts.erase(pre);
                        cx_itei=innards.erase(prei);
                        {
                            var o=c;
                            {
                                #if NAPE_ASSERT var res={
                                    o!=null;
                                };
                                if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZPP_Contact"+", in obj: "+"c"+")");
                                #end
                            };
                            o.free();
                            o.next=ZPP_Contact.zpp_pool;
                            ZPP_Contact.zpp_pool=o;
                        };
                        continue;
                    }
                    var ci=c.inner;
                    var pact=ci.active;
                    ci.active=c.stamp==stamp;
                    if(pact!=ci.active)contacts.modified=true;
                    if(ci.active){
                        var kn=mass_sum;
                        var kt=mass_sum;
                        if(!true){
                            {
                                ci.r1x=ci.px-b1.posx;
                                ci.r1y=ci.py-b1.posy;
                            };
                            var rcn=(ci.ny*ci.r1x-ci.nx*ci.r1y);
                            var rct=(ci.r1x*ci.nx+ci.r1y*ci.ny);
                            kn+=b1.sinertia*rcn*rcn;
                            kt+=b1.sinertia*rct*rct;
                        };
                        {
                            {
                                ci.r2x=ci.px-b2.posx;
                                ci.r2y=ci.py-b2.posy;
                            };
                            var rcn=(ci.ny*ci.r2x-ci.nx*ci.r2y);
                            var rct=(ci.r2x*ci.nx+ci.r2y*ci.ny);
                            kn+=b2.sinertia*rcn*rcn;
                            kt+=b2.sinertia*rct*rct;
                        };
                        ci.nMass=if(kn<ZPP_Const.EPSILON)0 else 1.0/kn;
                        ci.tMass=if(kt<ZPP_Const.EPSILON)0 else 1.0/kt;
                        var vrx:Float;
                        var vry:Float;
                        {
                            vrx=(if(!true)ci.r1y*b1.angvel else 0)-(ci.r2y*b2.angvel)-(if(!true)b1.velx else 0)+(b2.velx);
                            vry=(ci.r2x*b2.angvel)-(if(!true)ci.r1x*b1.angvel else 0)-(if(!true)b1.vely else 0)+(b2.vely);
                        };
                        var vdot=(ci.nx*vrx+ci.ny*vry);
                        ci.bias=c.dist+ZPP_Config.OVERLAP;
                        var nb=ZPP_Config.MIN_BIAS_COEF;
                        var delta=1-ZPP_Config.VEL_BIAS_COEF*vdot*vdot;
                        if(delta<0)delta=0;
                        delta-=c.dist*ZPP_Config.BIAS_PEN_COEF;
                        if(delta<0)delta=0;
                        if(delta>1)delta=1;
                        nb+=ZPP_Config.DEL_BIAS_COEF*delta;
                        if(nb>1)nb=1;
                        ci.jbAcc=0;
                        if(c.sBias==-1)c.sBias=nb;
                        else c.sBias=ZPP_Config.INT_BIAS_COEF*c.sBias+ZPP_Config.SUB_BIAS_COEF*nb;
                        if(ci.bias>0)ci.bias=0;
                        else ci.bias=-c.sBias*ci.bias;
                        ci.bounce=vdot*restitution;
                        vdot=(vry*ci.nx-vrx*ci.ny);
                        if(vdot*vdot>ZPP_Config.STATIC_VELSQ){
                            ci.friction=dyn_fric;
                        }
                        else{
                            ci.friction=stat_fric;
                        }
                    }
                    pre=cx_ite;
                    prei=cx_itei;
                    cx_itei=cx_itei.next;
                };
                cx_ite=cx_ite.next;
            }
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function applyImpulseCache(){
        {
            var cx_ite=contacts.begin();
            while(cx_ite!=null){
                var c=cx_ite.elem();
                {
                    var ci=c.inner;
                    if(!ci.active){
                        cx_ite=cx_ite.next;
                        continue;
                    };
                    c.pjnAcc=ci.jnAcc;
                    c.pjtAcc=ci.jtAcc;
                    {
                        var jx=ci.nx*ci.jnAcc-ci.ny*ci.jtAcc;
                        var jy=ci.ny*ci.jnAcc+ci.nx*ci.jtAcc;
                        if(!true){
                            {
                                var t=(b1.imass);
                                {
                                    #if NAPE_ASSERT var res={
                                        !({
                                            #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                            ret;
                                            #else Math.isNaN(t);
                                            #end
                                        });
                                    };
                                    if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_subeq(in a: "+"b1.vel"+",in b: "+"j"+",in s: "+"b1.imass"+")");
                                    #end
                                };
                                b1.velx-=jx*t;
                                b1.vely-=jy*t;
                            };
                            b1.angvel-=b1.iinertia*(jy*ci.r1x-jx*ci.r1y);
                        }
                        {
                            var t=(b2.imass);
                            {
                                #if NAPE_ASSERT var res={
                                    !({
                                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                        ret;
                                        #else Math.isNaN(t);
                                        #end
                                    });
                                };
                                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"b2.vel"+",in b: "+"j"+",in s: "+"b2.imass"+")");
                                #end
                            };
                            b2.velx+=jx*t;
                            b2.vely+=jy*t;
                        };
                        b2.angvel+=b2.iinertia*(jy*ci.r2x-jx*ci.r2y);
                    };
                };
                cx_ite=cx_ite.next;
            }
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function applyImpulse(elastic:Bool){
        {
            var cx_ite=innards.begin();
            while(cx_ite!=null){
                var c=cx_ite.elem();
                {
                    if(!c.active){
                        cx_ite=cx_ite.next;
                        continue;
                    };
                    var vrx:Float;
                    var vry:Float;
                    {
                        vrx=(if(!true)c.r1y*b1.bias_angvel else 0)-(c.r2y*b2.bias_angvel)-(if(!true)b1.bias_velx else 0)+(b2.bias_velx);
                        vry=(c.r2x*b2.bias_angvel)-(if(!true)c.r1x*b1.bias_angvel else 0)-(if(!true)b1.bias_vely else 0)+(b2.bias_vely);
                    };
                    var jbn=(c.bias-(vrx*c.nx+vry*c.ny))*c.nMass;
                    var jbOld=c.jbAcc;
                    var cjbAcc=jbOld+jbn;
                    if(cjbAcc<0)cjbAcc=0;
                    jbn=cjbAcc-jbOld;
                    c.jbAcc=cjbAcc;
                    {
                        var jx=c.nx*jbn-c.ny*0;
                        var jy=c.ny*jbn+c.nx*0;
                        if(!true){
                            {
                                var t=(b1.imass);
                                {
                                    #if NAPE_ASSERT var res={
                                        !({
                                            #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                            ret;
                                            #else Math.isNaN(t);
                                            #end
                                        });
                                    };
                                    if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_subeq(in a: "+"b1.bias_vel"+",in b: "+"j"+",in s: "+"b1.imass"+")");
                                    #end
                                };
                                b1.bias_velx-=jx*t;
                                b1.bias_vely-=jy*t;
                            };
                            b1.bias_angvel-=b1.iinertia*(jy*c.r1x-jx*c.r1y);
                        }
                        {
                            var t=(b2.imass);
                            {
                                #if NAPE_ASSERT var res={
                                    !({
                                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                        ret;
                                        #else Math.isNaN(t);
                                        #end
                                    });
                                };
                                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"b2.bias_vel"+",in b: "+"j"+",in s: "+"b2.imass"+")");
                                #end
                            };
                            b2.bias_velx+=jx*t;
                            b2.bias_vely+=jy*t;
                        };
                        b2.bias_angvel+=b2.iinertia*(jy*c.r2x-jx*c.r2y);
                    };
                    {
                        vrx=(if(!true)c.r1y*b1.angvel else 0)-(c.r2y*b2.angvel)-(if(!true)b1.velx else 0)+(b2.velx);
                        vry=(c.r2x*b2.angvel)-(if(!true)c.r1x*b1.angvel else 0)-(if(!true)b1.vely else 0)+(b2.vely);
                    };
                    var jn=((if(elastic)c.bounce else 0)+(c.nx*vrx+c.ny*vry))*c.nMass;
                    var jnOld=c.jnAcc;
                    var cjnAcc=jnOld-jn;
                    if(cjnAcc<0)cjnAcc=0;
                    jn=cjnAcc-jnOld;
                    c.jnAcc=cjnAcc;
                    var jt=((vry*c.nx-vrx*c.ny))*c.tMass;
                    var jtMax=c.friction*c.jnAcc;
                    var jtOld=c.jtAcc;
                    var cjtAcc=jtOld-jt;
                    if(cjtAcc>jtMax)cjtAcc=jtMax else if(cjtAcc<-jtMax)cjtAcc=-jtMax;
                    jt=cjtAcc-jtOld;
                    c.jtAcc=cjtAcc;
                    {
                        var jx=c.nx*jn-c.ny*jt;
                        var jy=c.ny*jn+c.nx*jt;
                        if(!true){
                            {
                                var t=(b1.imass);
                                {
                                    #if NAPE_ASSERT var res={
                                        !({
                                            #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                            ret;
                                            #else Math.isNaN(t);
                                            #end
                                        });
                                    };
                                    if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_subeq(in a: "+"b1.vel"+",in b: "+"j"+",in s: "+"b1.imass"+")");
                                    #end
                                };
                                b1.velx-=jx*t;
                                b1.vely-=jy*t;
                            };
                            b1.angvel-=b1.iinertia*(jy*c.r1x-jx*c.r1y);
                        }
                        {
                            var t=(b2.imass);
                            {
                                #if NAPE_ASSERT var res={
                                    !({
                                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                        ret;
                                        #else Math.isNaN(t);
                                        #end
                                    });
                                };
                                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"b2.vel"+",in b: "+"j"+",in s: "+"b2.imass"+")");
                                #end
                            };
                            b2.velx+=jx*t;
                            b2.vely+=jy*t;
                        };
                        b2.angvel+=b2.iinertia*(jy*c.r2x-jx*c.r2y);
                    };
                };
                cx_ite=cx_ite.next;
            }
        };
    }
}
